package com.czk.bootlettuce.controller;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Arrays;

/**
 * @author chenzhangkun
 * @ClassName LuaConfig
 * @description: TODO
 * @date 2024年03月19日
 */

@RestController
@RequestMapping("/lua")
public class LuaConfigController {

	@Resource
	private RedisTemplate redisTemplate;

	@RequestMapping("/test")
	public String lua() {
		String luaScript =
				"redis.call('SET',KEYS[1],ARGV[1])" +
						"redis.call('SET',KEYS[2],ARGV[2])";
		// Redis中执行 Lua脚本原子性是指：Lua脚本会作为一个整体执行且不被其他客户端打断，
		// 至于 Lua脚本里面的命令是否必须全部成功，或者全部失败，并不要求
		DefaultRedisScript<String> defaultRedisScript = new DefaultRedisScript<>();
		// 主从部署：Redis 主从复制是用于将主节点的数据同步到从节点，以保持数据的一致性。而Redis的所有写操作都在主节点上，
		// 所以，不管 Lua脚本中操作的 key是不是同一个，都能保证原子性；
		// 需要注意：当主节点执行写命令时，从节点会异步地复制这些写操作。在这个复制的过程中，从节点的数据可能与主节点存在一定的延迟。
		// 因此，如果在 Lua 脚本中包含读操作，并且该脚本在主节点上执行，可能会读到最新的数据，但如果在从节点上执行，可能会读到稍有延迟的数据。


		// 单机部署： Lua脚本中操作的 key是不是同一个，都能保证原子性；

		// 集群部署：如果 Lua脚本操作的 key是同一个，能保证原子性；
		//  如果操作的 Key不相同，可能被 hash 到不同的 slot，也可能 hash 到相同的 slot，所以不一定能保证原子性；
		//  因此，在 Cluster集群部署的环境下使用 Lua脚本时一定要注意：Lua脚本中操作的是同一个 Key；

		defaultRedisScript.setResultType(String.class);

		defaultRedisScript.setScriptText(luaScript);

		redisTemplate.execute(defaultRedisScript, Arrays.asList("czk", "czj"), "czkk", "czj");
		return "Ok";
	}

}
